import DeviceInfo from 'react-native-device-info'
import AsyncStorage from '@react-native-async-storage/async-storage'

import Blowfish from './crypto'

//prefix
const book = 'book'
const author = 'author'
const chapter = 'chapter'
const article = 'article'

const key = (...val) => val.join(':')

export class Persist {

  types = { book, author, chapter, article }

  crypto
  constructor(crypto = false) {
    if (crypto) {
      const _did = DeviceInfo.getDeviceId()
      this.crypto = new Blowfish(_did)
    }
  }

  get devicedId() {
    return DeviceInfo.getDeviceId()
  }

  encode(body) {
    const json = JSON.stringify(body)
    if (!this.crypto) return json
    return this.crypto.base64Encode(this.crypto.encrypt(json))
  }

  decode(body) {
    if (!this.crypto) return JSON.parse(body)
    return JSON.parse(this.crypto.decrypt(this.crypto.base64Decode(body)))
  }

  async get(type, id) {
    const body = await AsyncStorage.getItem(key(type, id))
    if (body) return this.decode(body)
  }

  async multiGet(keys) {
    const r = await AsyncStorage.multiGet(keys)
    return r.map(this.decode)
  }

  async set(type, body) {
    if (!body._id) return
    await AsyncStorage.setItem(key(type, body._id), this.encode(body))
  }

  async multiSet(type, ...vals) {
    await AsyncStorage.multiSet(vals.map(it => ([key(type, it._id), this.encode(it)])))
  }

  async update(type, body) {
    if (!body._id || this._crypto) return
    await AsyncStorage.mergeItem(key(type, body._id), JSON.stringify(body))
  }

  async remove(type, entry) {
    if (entry._id) {
      await AsyncStorage.removeItem(key(type, entry._id))
    } else {
      await AsyncStorage.removeItem(key(type, entry))
    }
  }

  async flush() {
    await AsyncStorage.clear()
  }
}

export default new Persist(true)